import { AUDIOPLAYMODE, AUDIOLYRICSHOW } from '../config.js'
import { randomSoleNumbers } from '@/assets/js/util.js'
import { openDB, closeDB, select, insert, update } from '@/assets/database'
//音乐播放
const state = {
	src: '',//当前播放链接
	poster: '',//当前封面
	creator: '',//创建者
	title: '',//标题
	referer: '',//请求来源
	lyrics: [],//歌词列表
	currentIndex: 0,//当前播放索引
	currentTime: 0,//播放时间
	duration: 0,//播放时长
	lyricIndex: 0,//歌词索引
	lyricTitle: '',//当前歌词
	playlist: [],//章节列表
	randoms: [],//随机播放列表
	paused: true,//是否暂停
	playMode: uni.getStorageSync(AUDIOPLAYMODE) || 'round', //播放模式
	lyricShow: uni.getStorageSync(AUDIOLYRICSHOW) || false, //是否显示全局歌词
}

const getters = {
	GET_CURRENT_SRC (state) {
		return state.src
	},
	GET_CURRENT_POSTER (state) {
		return state.poster
	},
	GET_CURRENT_CREATOR (state) {
		return state.creator
	},
	GET_CURRENT_TITLE (state) {
		return state.title
	},
	GET_CURRENT_REFERER (state) {
		return state.referer
	},
	GET_CURRENT_INDEX (state) {
		return state.currentIndex
	},
	GET_CURRENT_TIME (state) {
		return state.currentTime
	},
	GET_DURATION (state) {
		return state.duration
	},
	GET_LYRIC_INDEX (state) {
		return state.lyricIndex
	},
	GET_LYRIC_TITLE (state) {
		return state.lyricTitle
	},
	GET_PLAY_LIST (state) {
		return state.playlist
	},
	GET_RANDOM_LIST (state) {
		return state.randoms
	},
	GET_LYRIC_LIST (state) {
		return state.lyrics
	},
	GET_PAUSED (state) {
		return state.paused
	},
	GET_PLAY_MODE (state) {
		return state.playMode
	},
	GET_LYRIC_SHOW (state) {
		return state.lyricShow
	}
}

const mutations = {
	SET_CURRENT_SRC (state, src) {
		state.src = src
	},
	SET_CURRENT_POSTER (state, poster) {
		state.poster = poster
	},
	SET_CURRENT_CREATOR (state, creator) {
		state.creator = creator
	},
	SET_CURRENT_TITLE (state, title) {
		state.title = title
	},
	SET_CURRENT_REFERER (state, referer) {
		state.referer = referer
	},
	SET_CURRENT_INDEX (state, index) {
		state.currentIndex = index
	},
	SET_CURRENT_TIME (state, currentTime) {
		state.currentTime = currentTime
	},
	SET_DURATION (state, duration) {
		state.duration = duration
	},
	SET_LYRIC_INDEX (state, lyricIndex) {
		state.lyricIndex = lyricIndex
	},
	SET_LYRIC_TITLE (state, lyricTitle) {
		state.lyricTitle = lyricTitle
	},
	//设置播放列表
	SET_PLAY_LIST (state, playlist) {
		state.playlist = playlist
	},
	//设置随机播放列表
	SET_RANDOM_LIST (state, randoms) {
		state.randoms = randoms
	},
	//设置歌词列表
	SET_LYRIC_LIST (state, lyrics) {
		state.lyrics = lyrics
	},
	//设置当前播放状态
	SET_PAUSED (state, paused) {
		state.paused = paused
	},
	//设置播放模式
	SET_PLAY_MODE (state, playMode) {
		state.playMode = playMode || 'round'
		uni.setStorageSync(AUDIOPLAYMODE, state.playMode)
	},
	//设置是否显示全局歌词
	SET_LYRIC_SHOW (state, bol) {
		state.lyricShow = bol
		uni.setStorageSync(AUDIOLYRICSHOW, state.lyricShow)
	}
}

const actions = {
	//保存歌曲
	save ({state, commit}, song) {
		const list = [...state.playlist]
		const randoms = [...state.randoms]
		list.push(song)
		const newIndex = list.findIndex(item => item.audioId == song.audioId)
		if ( newIndex > -1 ) {
			const index = Math.floor(Math.random() * list.length)
			randoms.splice(index, 0, newIndex)
			commit('SET_PLAY_LIST', list)//增加歌曲
			commit('SET_RANDOM_LIST', randoms)//增加随机播放顺序
		}
	},
	//移除歌曲
	remove ({state, commit, dispatch}, id) {
		const list = [...state.playlist]
		const randoms = [...state.randoms]
		const index = list.findIndex(item => item.audioId == id)
		if ( index > -1 ) {
			list.splice(index, 1)
			const randomIndex = randoms.indexOf(index)
			if ( randomIndex > -1 ) randoms.splice(randomIndex, 1)
			commit('SET_PLAY_LIST', list)//移除播放列表的歌曲
			commit('SET_RANDOM_LIST', randoms)//移除对应的随机歌曲顺序
			const newIndex = state.currentIndex - 1
			if ( index == state.currentIndex ){ //移除的是当前播放的歌曲
				if ( list.length > 0 ) {//如果播放列表还有歌曲继续播放下一首
					commit('SET_CURRENT_INDEX', newIndex)//重置新播放列表的当前播放索引值
					dispatch('next', true)
				} else {//没有歌曲，则注销音频播放器
					dispatch('stop')
					dispatch('clear')
				}
			} else {//移除的是非当前播放的歌曲
				commit('SET_CURRENT_INDEX', newIndex)//重置新播放列表的当前播放索引值
			}
		}
	},
	//插入歌曲列表
	insert ({state, commit}, songs) {
		const list = [...state.playlist]
		const randoms = [...state.randoms]
		const newList = list.concat(songs)
		songs.forEach(song => {//新增歌曲需要新增随机播放顺序
			const newIndex = newList.findIndex(item => item.audioId == song.audioId)
			if ( newIndex > -1 ) {
				const index = Math.floor(Math.random() * newList.length)
				randoms.splice(index, 0, newIndex)
			}
		})
		commit('SET_RANDOM_LIST', randoms)//增加随机播放顺序
		commit('SET_PLAY_LIST', newList)//增加歌曲列表
	},
	//替换播放列表
	replace ({commit, dispatch}, list) {
		commit('SET_PLAY_LIST', list)
		commit('SET_RANDOM_LIST', randomSoleNumbers(list.length))
	},
	//切换播放模式
	switchPlayMode ({state, commit}) {
		switch ( state.playMode ) {
			case 'round':
				commit('SET_PLAY_MODE', 'loop')
				break
			case 'loop':
				commit('SET_PLAY_MODE', 'random')
				break
			default:
				commit('SET_PLAY_MODE', 'round')
				break
		}
	},
	//切换歌词显示
	switchLyricShow ({state, commit}) {
		commit('SET_LYRIC_SHOW', !state.lyricShow)
	},
	prev ({state, commit, dispatch}) {
		const length = state.playlist.length
		const currentIndex = parseInt(state.currentIndex)
		if ( state.playMode == 'random' && length > 1 ) {//随机播放
			const randomIndex = state.randoms.indexOf(currentIndex)
			const index = randomIndex - 1 >= 0 ? randomIndex - 1 : length - 1
			const playIndex = state.randoms[index]
			dispatch('change', state.playlist[playIndex].audioId)
		} else if ( state.playMode == 'round' && length > 1 ) {//顺序播放
			const index = currentIndex - 1 >= 0 ? currentIndex - 1 : length - 1
			dispatch('change', state.playlist[index].audioId)
		} else {//单曲循环
			uni.$emit('seekSong', 0)
			uni.$emit('play')
		}
	},
	next ({state, commit, dispatch}, isRemove = false) {
		const length = state.playlist.length
		const currentIndex = parseInt(state.currentIndex)
		if ( state.playMode == 'random' && (length > 1 || isRemove) ) {//随机播放
			const randomIndex = state.randoms.indexOf(currentIndex)
			const index = randomIndex + 1 < length ? randomIndex + 1 : 0
			const playIndex = state.randoms[index]
			dispatch('change', state.playlist[playIndex].audioId)
		} else if ( state.playMode == 'round' && (length > 1 || isRemove) ) {//顺序播放
			const index = currentIndex + 1 < length ? currentIndex + 1 : 0
			dispatch('change', state.playlist[index].audioId)
		} else {//单曲循环
			uni.$emit('seekSong', 0)
			uni.$emit('play')
		}
	},
	async change ({state, commit, rootGetters}, id) {
		const list = state.playlist
		const index = list.findIndex(item => item.audioId == id)
		if ( list[index] ) {
			const detail = list[index].detail
			const item = list[index].item
			const network = rootGetters['network/GET']
			commit('SET_CURRENT_INDEX', index)//全部播放列表的index索引
			commit('SET_CURRENT_TITLE', item.title || item.name || detail.title)
			commit('SET_CURRENT_POSTER', item.poster || item.cover || detail.cover)
			commit('SET_CURRENT_CREATOR', item.creator || item.singer || item.subtitle || detail.subtitle)
			const newItem = await getContext(network, list[index])
			const lyrics = await getLyrics(network, Object.assign({}, list[index], {item: newItem}))
			if ( newItem.src != state.src ) {//如果新的播放链接和当前播放链接是一样的，则不清空播放时长和播放状态
				commit('SET_CURRENT_TIME', 0)
				commit('SET_DURATION', 1)
				commit('SET_PAUSED', true)
			}
			const globalConfig = network.source.globalConfig || {}//获取公共配置
			commit('SET_CURRENT_REFERER', newItem.referer || detail.referer || globalConfig.audioReferer)//设置请求来源（处理防盗链）
			commit('SET_LYRIC_LIST', lyrics || [])
			commit('SET_CURRENT_SRC', newItem.src || 'undefined')//如果没有播放链接，则给一个字符串，为了触发音频播放器加载错误事件，自动切换音频
			if ( newItem.title || newItem.name ) commit('SET_CURRENT_TITLE', newItem.title || newItem.name)
			if ( newItem.poster || newItem.cover ) commit('SET_CURRENT_POSTER', newItem.poster || newItem.cover || detail.cover)
			if ( newItem.creator || newItem.singer || newItem.subtitle ) commit('SET_CURRENT_CREATOR', newItem.creator || newItem.singer || newItem.subtitle)
			if ( [0, 1].includes(rootGetters['setting/GET_HISTORY']) ) {
				await openDB()
				const data = await select('record', 'unique_id = "' + detail.uniqueId + '"')
				const record = data.list[0] || {}
				try{
					if ( record.id ) {
						await update('record', {
							url: detail.url,
							title: detail.title || '',
							cover: detail.cover || '',
							current: list[index].current,//当前歌曲列表的索引，非整个播放列表的索引
							position: state.currentTime,
							currentTitle: state.title,
							is_adult: detail.isAdult,
							source_id: detail.sourceId
						}, 'id = ' + record.id)
					} else {
						await insert('record', {
							unique_id: detail.uniqueId,
							url: detail.url,
							title: detail.title || '',
							cover: detail.cover || '',
							current: list[index].current,//当前歌曲列表的索引，非整个播放列表的索引
							position: state.currentTime,
							currentTitle: state.title,
							is_adult: detail.isAdult,
							source_id: detail.sourceId
						})
					}
					closeDB()
				}catch(e){
					closeDB()
					uni.showToast({
						title: e.message,
						icon: 'none'
					})
				}
			}
			
		}
	},
	//停止音频播放
	stop ({commit}) {
		commit('SET_PAUSED', true)
		commit('SET_CURRENT_INDEX', 0)
		commit('SET_CURRENT_SRC', '')
		commit('SET_CURRENT_TIME', 0)
		commit('SET_DURATION', 1)
		commit('SET_LYRIC_INDEX', 0)
		commit('SET_LYRIC_TITLE', '')
		commit('SET_LYRIC_LIST', [])
	},
	//清空播放列表
	clear ({commit, dispatch}) {
		dispatch('stop')
		commit('SET_CURRENT_TITLE', '')
		commit('SET_CURRENT_CREATOR', '')
		commit('SET_CURRENT_POSTER', '')
		commit('SET_PLAY_LIST', [])
		commit('SET_RANDOM_LIST', [])
	}
}

const getContext = async function (network, audio) {
	const context = audio.context || {}
	const request = context.request
	const params = Object.assign({}, audio.query, audio.detail, audio.item)
	const staticData = context.staticData ? await network.staticDataHandle(context.staticData, params) : {}
	const dynamicData = context.dynamicData || {}
	const newRequest = request ? await network.requestHandle(request, params) : null
	const response = newRequest ? await network.$request(newRequest) : {}
	const data = response.data ? await network.$list(dynamicData, response.data, response.taskId) : null
	return Object.assign({}, audio.item, staticData, data)
}
const getLyrics = async function  (network, audio) {
	const lyrics = audio.lyrics || {}
	const params = Object.assign({}, audio.query, audio.detail, audio.item)
	const staticData = lyrics.staticData ? await network.staticDataHandle(lyrics.staticData, params) : []
	const dynamicData = lyrics.dynamicData
	const request = lyrics.request
	let data = []
	if ( dynamicData && request ) {
		const newRequest = await network.requestHandle(request, params)
		const response = await network.$request(newRequest)
		data = await network.$list(dynamicData, response.data, response.taskId)
	}
	return staticData.concat(data)
}

export default {
    namespaced: true,
    state,
    getters,
    mutations,
	actions
}
